/*
 * UtilAnalizador.java	
 *
 * Copyright 2008 Universidad Francisco de Paula Santander (UFPS).
 * Todos los Derechos Reservados.
 * Creado el 01/05/10, 13:23:38 PM
 */

package com.ufps.cuatro.modelo.analizador;

import com.ufps.cuatro.controlador.render.UtilRender;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JWindow;

import com.ufps.cuatro.modelo.representacion.UtilRepresentacion;
import com.ufps.cuatro.util.IconoFileChooser;
import com.ufps.cuatro.util.Utileria;
import com.ufps.cuatro.util.UtileriaBase;
import com.ufps.cuatro.util.opciones.MyProperties;
import javax.swing.JFileChooser;

/**
 * <i><b>UtilAnalizador:</b></i><p>Clase Utilitaria de Recursos generales para el Módulo.</p>
 * <p>Brinda Recursos y Utilidades en el Proceso de Análisis del Jar que 
 * representa el Modelo de Clases del Usuario.</p>
 *
 * @author  Carlos A. Torres C. - Dolly E. Guerrero. <https://code.google.com/p/tesis4dor/>
 * @version 1.0 01/05/10
 * @see UtileriaBase
 */
public abstract class UtilAnalizador extends UtileriaBase{

    /**
     * Colección de los Nombre de la Clases Identificadas en el Modelo Analizado.
     */
    public static ArrayList<String> objNombresClases;
    /**
     * Colección de las Clases Identificadas en el Modelo Analizado.
     */
    public static ArrayList<ObjetoReflexion> objClases;
    
    /**
     * Variable static para almacenar los Recursos en las Subclases.
     */
    public static org.jdesktop.application.ResourceMap resourceMap;
    
    static{
        try{
            init();
        }catch(java.lang.Exception ex){
            System.out.println("Error de Inicialización de Contexto.");
        }       
    }
    
    private static void init(){
        resourceMap = org.jdesktop.application.Application.getInstance(com.ufps.cuatro.CuatroApp.class).getContext().getResourceMap(UtilAnalizador.class);        
    }
    
    /**
     * Devuelve el Recurso de Texto Asociado a la Clave recibida en el Parametro ó
     * un Cadena vacia en Caso de no encontrarse ó presentarse un Error.
     * @param key Clave recibida.
     * @return Recurso de Texto Asociado a la Clave recibida en el Parametro.
     * @see org.jdesktop.application.ResourceMap#getString(java.lang.String, java.lang.Object[]) 
     * @throws ResourceMap.LookupException
     * @throws java.lang.IllegalArgumentException
     */
    public static String leerRecursoTexto(String key){
        try{
            if(resourceMap.containsKey(key)){
                return resourceMap.getString(key);
            }
        }catch(java.lang.NullPointerException ex){
            UtilRender.printlnConsole(ex.getMessage(), UtilRender.ACTION_ERROR, true);
        }
        return "";
    }

    /**
     * Devuelve el Icono de la Aplicación de acuerdo  al tamaño recibido en el Parametro.
     * @param modo 
     * @return Icono de la Aplicación de acuerdo  al tamaño recibido en el Parametro.
     * @see org.jdesktop.application.ResourceMap#getIcon(java.lang.String) 
     * @throws ResourceMap.LookupException
     * @throws java.lang.IllegalArgumentException
     */
    public static Icon leerIconoApp(int modo){
      try{  
            String key = "Utileria.icono.app." + String.valueOf(modo);
            return resourceMap.getIcon(key);
        }catch(java.lang.NullPointerException ex){
            UtilRender.printlnConsole(ex.getMessage(), UtilRender.ACTION_ERROR, true);
        }
      return null;
    }

    /**
     * Devuelve el Icono de la Aplicación en Formato Imagen de acuerdo  al tamaño recibido en el Parametro.
     * @param modo 
     * @return Icono de la Aplicación en Formato Imagen de acuerdo  al tamaño recibido en el Parametro.
     * @see org.jdesktop.application.ResourceMap#getIcon(java.lang.String) 
     * @throws ResourceMap.LookupException
     * @throws java.lang.IllegalArgumentException
     */
    public static ImageIcon leerIconoAppEnImagen(int modo){
       try{
            String key = "Utileria.icono.app." + String.valueOf(modo);
            return resourceMap.getImageIcon(key);
        }catch(java.lang.NullPointerException ex){
            UtilRender.printlnConsole(ex.getMessage(), UtilRender.ACTION_ERROR, true);
        }
       return null;
    }    
    
    /**
     * Devuelve el Recurso de Gráfico de Icono Asociado a la Clave y al Tamaño recibidos 
     * en los Parametros.
     * @param key Clave recibida.
     * @param size Tamaño del Icono.
     * @return Recurso de Gráfico de Icono Asociado a la Clave y al Tamaño recibidos 
     * en los Parametros.
     * @see org.jdesktop.application.ResourceMap#getIcon(java.lang.String) 
     * @throws ResourceMap.LookupException
     * @throws java.lang.IllegalArgumentException
     */
    public static Icon leerRecursoIcono(String key, int size){
        try{
            String strPath = null;
            if(size == 16){
                strPath = key.replaceAll("32x32", "16x16");
            }
            else if(size == 32){
                strPath = key.replaceAll("16x16", "32x32");
            }    
            strPath += UtileriaBase.leerRecursoTexto(key);
            return resourceMap.getIcon(strPath);        
        }catch(java.lang.NullPointerException ex){
            UtilRender.printlnConsole(ex.getMessage(), UtilRender.ACTION_ERROR, true);
        }
        return null;
    }    
    
    /**
     * Devuelve el Recurso de Gráfico de Imagen Asociado a la Clave y al Tamaño recibidos 
     * en los Parametros.
     * @param key Clave recibida.
     * @param size Tamaño de la Imagen.
     * @return Recurso de Gráfico de Imagen Asociado a la Clave y al Tamaño recibidos 
     * en los Parametros.
     * @see org.jdesktop.application.ResourceMap#getIcon(java.lang.String) 
     * @throws ResourceMap.LookupException
     * @throws java.lang.IllegalArgumentException
     */
    public static ImageIcon leerRecursoImagen(String key, int size){        
        try{
            String strPath = "";
            if(size == UtileriaBase.SIZE_ICON_16){
                strPath = key.replaceAll("32x32", "16x16");
            }
            else if(size == UtileriaBase.SIZE_ICON_32){
                strPath = key.replaceAll("16x16", "32x32");
            }        
            return resourceMap.getImageIcon(strPath);
        }catch(java.lang.NullPointerException ex){
            UtilRender.printlnConsole(ex.getMessage(), UtilRender.ACTION_ERROR, true);
        }
        return null;
    }
    
    /**
     * Carga un Archivo Properties en el formato válido de la Aplicación
     * para la administración de este tipo de archivo.
     * @param strPath Ruta de la Ubicación del Recurso.
     * @return Archivo Properties ecansulado en un objeto <code>MyProperties</code>.
     */
    public static MyProperties cargar(String strPath){
       try{
           URL url = resourceMap.getClassLoader().getResource(strPath);
           try {
               MyProperties objPropiedades = new MyProperties(url.toURI());
               return objPropiedades;
           } catch (IOException ex) {
               Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
           } catch (URISyntaxException ex) {
               Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
           }
           return null;
       }catch(java.lang.NullPointerException ex){
           UtilRender.printlnConsole(ex.getMessage(), UtilRender.ACTION_ERROR, true);
       }
       return null;
    }
    
    /**
     * Carga un Archivo Properties en el formato válido de la Aplicación
     * para la administración de este tipo de archivo.
     * @param objPath Ruta de la Ubicación del Recurso.
     * @return Archivo Properties ecansulado en un objeto <code>MyProperties</code>.
     */
    public static MyProperties cargarFileProperties(File objPath){
        try{
            try {            
                MyProperties objPropiedades = new MyProperties(objPath.toURI());
                return objPropiedades;
            } catch (IOException ex) {
                Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
            } 
        }catch(java.lang.NullPointerException ex){
            UtilRender.printlnConsole(ex.getMessage(), UtilRender.ACTION_ERROR, true);
        }
        return null;
    }
    
    /**
     * Elimina la Extensión del Archivo.
     * @param strFile Nombre del Archivo.
     * @return Nombre del Archivo sin extensión.
     */
    public static String eliminarExtension(String strFile){
       try{
           int fin = 0;
           fin = strFile.indexOf(".");
           if(fin == -1) {
               return strFile;
           }
           strFile = strFile.substring(0, fin);
           return strFile;
       }catch(java.lang.NullPointerException ex){
           UtilRender.printlnConsole(ex.getMessage(), UtilRender.ACTION_ERROR, true);
       }
       return "";
    }

    /**
     * Elimina la Extensión del Archivo.
     * @param strFile Nombre del Archivo.
     * @return Nombre del Archivo sin extensión.
     */
    @SuppressWarnings("empty-statement")
    public static String eliminarExtensionBack(String strFile){
        if(strFile != null){
            if(!strFile.isEmpty()){
                int fin = 0;
                int size = strFile.length();            
                while(strFile.charAt(size - ++fin) != '.');
                if(size > 0){
                    return strFile.substring(0, size - fin);
                }
            }
            return strFile;
        }else{
            UtilRender.printlnConsole("String Nulo.", UtilRender.ACTION_NORMAL, false);            
        } 
        return "";
    }

    /**
     * Evalua si el Classpath esta registrado en la ejecución actual.
     * @param strClassPath Cadena de Definición de la Clase que se Evaluará.
     * @return Resultado de la Evaluación del Classpath.
     */
    public static boolean estaRegistradaEnElClassPath(String strClassPath){
        try{
            if(strClassPath == null)return false;
            try {
                // Cargamos la clase
                if(!strClassPath.isEmpty()){
                    Class<?> clase = Class.forName(strClassPath);
                    return true;
                }            
            } catch (ClassNotFoundException ex) {
                //Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);            
            } catch (Exception ex) {
               //Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);            
            }
        }catch(java.lang.NullPointerException ex){
            UtilRender.printlnConsole(ex.getMessage(), UtilRender.ACTION_ERROR, true);
        }
        return false;               
    }
    
    /**
     * Determina si un ClassPath hace parte de los Paquetes Grafica Estandares de Java
     * java.awt y java.swing.
     * @param strClassPath ClassPath que se evaluará.
     * @return boolean que determina si el ClassPath hace parte de los Paquetes Grafica Estandares de Java
     * java.awt y java.swing.
     */
    public static boolean esClaseGrafica(String strClassPath){               
       try{
        Class<?> clase = null;        
        try {
            if(strClassPath != null){
                if(!strClassPath.isEmpty()){
                    if(strClassPath.contains("$"))return true;
                    // Cargamos la clase
                    clase = Class.forName(strClassPath);
                    String strClassInstance = strClassPath;
                    while(!strClassInstance.equals("java.lang.Object")){
                        if(esStringClaseGraficaSwing(strClassInstance))return true;
                        clase = clase.getSuperclass();
                        strClassInstance = clase.getCanonicalName();
                    }
                    Object obj = clase.newInstance();
                    return esObjetoClaseGraficaSwing(obj);
                }
            }
        } catch (InstantiationException ex) {
            Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NullPointerException ex) {
            Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
        }
        }catch(java.lang.NullPointerException ex){}
        return true;
    }
    
    /**
     * Evalua si un classPath pertenece a los paquetes Estandares Graficos de java.
     * @param strClassPath ClassPath que se evaluará.
     * @return boolean que determina si el ClassPath hace parte de los Paquetes Grafica Estandares de Java
     * java.awt y java.swing.
     */
    public static boolean esStringClaseGraficaSwing(String strClassPath){        
        try{
            if(strClassPath != null){
                if(strClassPath.equals("javax.swing.JComponent") ||
                        strClassPath.equals("javax.swing.JFrame") ||
                        strClassPath.equals("javax.swing.JDialog") ||
                        strClassPath.equals("javax.swing.JPanel") ||
                        strClassPath.equals("javax.swing.JWindow") ||
                        strClassPath.equals("java.awt.Component")){
                    return true;
                }
            }
        }catch(java.lang.NullPointerException ex){
            UtilRender.printlnConsole(ex.getMessage(), UtilRender.ACTION_ERROR, true);
        }
        return false;
    }
    
    /**
     * Evalua si un Objeto pertenece a los paquetes Estandares Graficos de java.
     * @param strClassPath ClassPath que se evaluará.
     * @param obj Objeto que se evaluará.
     * @return boolean que determina si el Objeto hace parte de los Paquetes Grafica Estandares de Java
     * java.awt y java.swing.
     */
    public static boolean esObjetoClaseGraficaSwing(Object obj){        
       try{ 
            if(obj != null){
                if(obj instanceof JComponent ||
                        obj instanceof JFrame ||
                        obj instanceof JDialog ||
                        obj instanceof JPanel ||
                        obj instanceof JWindow){
                    return true;
                }
            } 
       }catch(java.lang.NullPointerException ex){
           UtilRender.printlnConsole(ex.getMessage(), UtilRender.ACTION_ERROR, true);
       }
       return false;
    }

    /**
     * Evalua si el modificador esta presente en el Objeto Class.
     * @param objClass Objeto Class.
     * @param modificador Modificador de Acceso.
     * @return Resultado de la Evaluación.
     */
    public static boolean estaPresenteModificadorEnClase(Class<?> objClass, int modificador){
       try{ 
           try {
               return objClass.getModifiers() == modificador;                        
           } catch (Exception ex) {        
               UtilRender.printlnConsole(ex.getMessage(), UtilRender.ACTION_ERROR, true);
           }
       }catch(java.lang.NullPointerException ex){
           UtilRender.printlnConsole(ex.getMessage(), UtilRender.ACTION_ERROR, true);
       }
       return false;
    }

    /**
     * Crea una Instancia Generica de un Objeto por medio de un Classpath.
     * @param strClassPath Cadena de Definición para el Objeto.
     * @return Resultado de la Instanciación.
     */
    public static Object crearInstancia(String strClassPath){
        if(strClassPath != null){
            Class<?> clase = null;
            Object objeto = null;
            try {
                // Cargamos la clase
                clase = Class.forName(strClassPath);
                objeto = clase.newInstance();
                return objeto;
            } catch (InstantiationException ex) {
                Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        else{
            UtilRender.printlnConsole("String Nulo.", UtilRender.ACTION_NORMAL, false);            
        }
        return null;
    }
    
    /**
     * Crea una Instancia Generica de un Objeto Class.
     * @param objClase Objeto Class.
     * @return Resultado de la Instanciación.
     */
    public static Object crearInstancia(Class<?> objClase){        
        if( objClase != null){
        Object objeto = null;
        try {
            // Se Crea el Objeto
            objeto = objClase.newInstance();
            return objeto;
        } catch (InstantiationException ex) {
            String strNotificacion = "<html><p>La Clase: <b>" + objClase.getCanonicalName() + "</b>" + 
                    " no posee un Constructor sin Argumentos  ej: <i> new " + objClase.getSimpleName() + "()</i> esto limita la generación" +
                    " automática de representaciones por medio del Patron de Representaciones.</p><p>Se recomienda" + 
                    " implementar el Constructor para lograr mejores resultados en las representaciones" +
                    " de ese tipo de dato.</p><p>----------------------------------------------------------</p></html>";
            if(!UtilRepresentacion.objBibliotecaTrabajoLocal.getObjNotificacionesModeloAnalizado().contains(strNotificacion)){
                UtilRepresentacion.objBibliotecaTrabajoLocal.addNotificacionModeloAnalizado(strNotificacion);
            }
            Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
        }
        }
        else{
            UtilRender.printlnConsole("String Nulo.", UtilRender.ACTION_NORMAL, false);            
        }
        return null;
    }
    
    public static File getFileOpenSelectedJar(){
        try{
            if(Utileria.objFrame != null){
                String strDescripcion   = Utileria.leerRecursoTexto("Utileria.file.jar.descripcion");
                String strExtension     = Utileria.leerRecursoTexto("Utileria.file.jar.ext");
                String strLabelButtonOk = Utileria.leerRecursoTexto("Utileria.label.button.load.jar");
                return UtilAnalizador.getFileOpenSelected(Utileria.strTempDir, strDescripcion, strExtension, strLabelButtonOk);         
            }
        }catch(java.lang.Exception ex) {
            Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
    
    public static File getFileOpenSelectedModel(){
        try{
            if(Utileria.objFrame != null){
                String strDescripcion       = Utileria.leerRecursoTexto("Utileria.file.dor.descripcion");
                String strExtension         = Utileria.leerRecursoTexto("Utileria.file.dor.ext");
                String strLabelButtonOk     = Utileria.leerRecursoTexto("Utileria.label.button.load.model");
                IconoFileChooser objIcono   = new IconoFileChooser();
                return UtilAnalizador.getFileOpenSelected(objIcono, Utileria.strTempDir, strDescripcion, strExtension, strLabelButtonOk);                 
            }
        }catch(java.lang.Exception ex) {
            Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;    
    }
    
    private static File getFileOpenSelected(String strInitDir, String strDescripcion, String strExtension, String strLabelButtonOk){
        
        javax.swing.JFileChooser fc = new JFileChooser();
        
        if(!strDescripcion.isEmpty() && !strExtension.isEmpty()){                           
            javax.swing.filechooser.FileNameExtensionFilter filter = 
                    new javax.swing.filechooser.FileNameExtensionFilter(strDescripcion, strExtension);
            
            fc.setFileFilter(filter);

            File fileDir = null;

            if (strInitDir.compareTo("") == 0) {
                fc.changeToParentDirectory();
            } 
            else {
                fileDir = new File(strInitDir);
                fc.setCurrentDirectory(fileDir);
            }       

            if(strLabelButtonOk.isEmpty()){
                strLabelButtonOk = "Aceptar";
            }

            try{
                int option = fc.showDialog(fc, strLabelButtonOk);        
                if (JFileChooser.APPROVE_OPTION == option) {
                    if(fc.getSelectedFile().exists()){                
                        File objOutPutFile = fc.getSelectedFile();                
                        return objOutPutFile;
                    }            
                }
            }catch( java.awt.HeadlessException ex){
                Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return null;
    }
    
    private static File getFileOpenSelected(IconoFileChooser objIcono, String strInitDir, String strDescripcion, String strExtension, String strLabelButtonOk){
        javax.swing.JFileChooser fc = new JFileChooser();
        
        if(!strDescripcion.isEmpty() && !strExtension.isEmpty()){
            javax.swing.filechooser.FileNameExtensionFilter filter = 
                    new javax.swing.filechooser.FileNameExtensionFilter(
                        strDescripcion,
                        strExtension);

            fc.setFileFilter(filter);
        }
        
        if(objIcono != null){
            fc.setFileView(objIcono);
        }   
        
        File fileDir = null;
        
        if (strInitDir.compareTo("") == 0) {
            fc.changeToParentDirectory();
        } else {
            fileDir = new File(strInitDir);
            fc.setCurrentDirectory(fileDir);
        }
        
        if(strLabelButtonOk.isEmpty()){
            strLabelButtonOk = "Aceptar";
        }
        
        try{
            int option = fc.showDialog(fc, strLabelButtonOk);        
            if (JFileChooser.APPROVE_OPTION == option) {
                if(fc.getSelectedFile().exists()){                
                    File objOutPutFile = fc.getSelectedFile();                
                    return objOutPutFile;
                }            
            }
        }catch( java.awt.HeadlessException ex){
            Logger.getLogger(UtilAnalizador.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
}
